home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / TestParts / Clock / ClockPrt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  46.7 KB  |  1,753 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ClockPrt.cpp
  3.  
  4.     Contains:    ClockPart C++ helper object
  5.  
  6.     Owned by:    Richard Rodseth
  7.  
  8.     Copyright:    © 1995 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <3>      10/15/96    JP        1375124 : Used Active Part prop when
  13.                                     recording.
  14.          <2>     7/16/96    EL        1295068: Do not externalize unless it is
  15.                                     dirty.
  16.         <28>    10/23/95    RR        #1291688 Added test for adding New menus
  17.         <27>    10/18/95    RR        1289153: Recover from exceptions creating
  18.                                     windows. Store fPlatformWindow pointer in
  19.                                     ClockFrame, so we can get to it even if
  20.                                     odWindow isn't successfully created.
  21.                                     Release remaining frames in ReleaseAll().
  22.         <26>    10/17/95    jpa        Recover from exceptions thrown by
  23.                                     RegisterWindowForFrame [1289153]
  24.         <25>    10/16/95    RR        #1293067 Pass shouldDispose to
  25.                                     RegisterWindow
  26.         <24>    25/09/95    NP        1979071: Check results of operator new.
  27.         <23>     9/21/95    RR        Allocate synch dialog out of temp mem
  28.         <22>     9/12/95    RR        Various activation problems. Added a
  29.                                     floating window
  30.         <21>     9/12/95    JP        1280292 & 1283803: Add Part to Send
  31.         <20>     9/11/95    NP        1272294: Messaging code cleanup.
  32.         <19>      9/1/95    RR        # 1244639 Delete window record when frame
  33.                                     is closed/removed
  34.         <18>     8/25/95    JP        1268279: Send part to frame fallout
  35.         <17>     8/15/95    RR        HandleOSEvent improvements
  36.         <16>      8/8/95    jpa        Removed DebugStrs [1265584]
  37.         <15>     7/10/95    RR        Misc. cleanup and bug fixes for shared
  38.                                     window
  39.         <14>     7/10/95    JP        Scripting cleanup
  40.         <13>      7/7/95    RR        Some refactoring. Fix
  41.                                     CreatePropObjSpecifier to deal with
  42.                                     non-persistent frame. Set source frame of
  43.                                     dialogs.
  44.         <12>      7/3/95    RR        Added #if ODDebug around DebugStr
  45.         <11>     6/30/95    RR        1242642 BB Ref counting fixes. Display
  46.                                     settings window is saved as an ID, not a
  47.                                     window
  48.         <10>     6/29/95    VL        1242642: Release the created su in
  49.                                     CloneInto.
  50.          <9>     6/25/95    TÇ        1242642 BB: Turn on ODDebug warning if
  51.                                     refcount is wrong in
  52.                                     ODRefCntObjectsomUninit.
  53.          <8>     6/22/95    jpa        (oops, removed bogus in progress comment.)
  54.          <7>     6/22/95    jpa        Fixed refcounting of semantic interface.
  55.                                     [1261644]
  56.          <6>     6/20/95    JP        1251250: Acquire & Release extension
  57.                                     properly
  58.          <5>     6/13/95    JP        Recordable Clock
  59.          <4>      6/8/95    jpa        Use temp objects (TempODShape,
  60.                                     TempODFrame). [1246062]
  61.          <3>      6/8/95    RR        #1257260 Collapse base classes. #1214898
  62.                                     StdTypes.r -> ODTypes.r
  63.          <2>      6/3/95    TJ        Added #includes for compile with out PCH
  64.          <1>     5/31/95    RR        first checked in
  65.  
  66.     To Do:
  67.     In Progress:
  68.         
  69. */
  70.  
  71. #ifndef _ALTPOINT_
  72. #include "AltPoint.h"            // Use C++ savvy ODPoint and ODRect
  73. #endif
  74.  
  75. #ifndef _ODTYPES_
  76. #include <ODTypes.h>
  77. #endif
  78.  
  79. #ifndef SOM_ODRefCntObject_xh
  80. #include "RefCtObj.xh"
  81. #endif
  82.  
  83. #ifndef SOM_ODPart_xh
  84. #include "Part.xh"
  85. #endif
  86.  
  87. #ifndef _CLOCKFRM_
  88. #include "ClockFrm.h"
  89. #endif
  90.  
  91. #ifndef _CLOCKGBL_
  92. #include "ClockGbl.h"
  93. #endif
  94.  
  95. #ifndef _CLOCKPRT_
  96. #include "ClockPrt.h"
  97. #endif
  98.  
  99. #ifndef _CLOCKDEF_
  100. #include "ClockDef.h"
  101. #endif
  102.  
  103. #ifndef _PLFMDEF_
  104. #include "PlfmDef.h"
  105. #endif
  106.  
  107.  
  108. #ifndef _SIHELPER_
  109. #include "SIHelper.h"
  110. #endif
  111.  
  112. #ifndef SOM_Module_OpenDoc_Foci_defined
  113. #include <Foci.xh>
  114. #endif
  115.  
  116. #ifndef _USERSRCM_
  117. #include "UseRsrcM.h"
  118. #endif
  119.  
  120. #ifndef SOM_ODFocusSet_xh
  121. #include <FocusSet.xh>
  122. #endif
  123.  
  124. #ifndef SOM_Module_OpenDoc_StdProps_defined
  125. #include <StdProps.xh>
  126. #endif
  127.  
  128. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  129. #include <StdTypes.xh>
  130. #endif
  131.  
  132.  
  133. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  134. #include <StdDefs.xh>
  135. #endif
  136.  
  137. #ifndef SOM_ODDraft_xh
  138. #include <Draft.xh>
  139. #endif
  140.  
  141. #ifndef SOM_ODDocument_xh
  142. #include <Document.xh>
  143. #endif
  144.  
  145. #ifndef SOM_ODContainer_xh
  146. #include <ODCtr.xh>
  147. #endif
  148.  
  149. #ifndef SOM_ODStorageUnit_xh
  150. #include <StorageU.xh>
  151. #endif
  152.  
  153. #ifndef SOM_ODStorageUnitView_xh
  154. #include <SUView.xh>
  155. #endif
  156.  
  157. #ifndef SOM_ODStorageUnitCursor_xh
  158. #include <SUCursor.xh>
  159. #endif
  160.  
  161. #ifndef SOM_ODSession_xh
  162. #include <ODSessn.xh>
  163. #endif
  164.  
  165. #ifndef SOM_ODWindowState_xh
  166. #include <WinStat.xh>
  167. #endif
  168.  
  169. #ifndef SOM_ODFrame_xh
  170. #include <Frame.xh>
  171. #endif
  172.  
  173. #ifndef SOM_ODFacet_xh
  174. #include <Facet.xh>
  175. #endif
  176.  
  177. #ifndef SOM_ODFrameFacetIterator_xh
  178. #include <FrFaItr.xh>
  179. #endif
  180.  
  181. #ifndef _ORDCOLL_
  182. #include "OrdColl.h"
  183. #endif
  184.  
  185. #ifndef SOM_ODDispatcher_xh
  186. #include <Disptch.xh>
  187. #endif
  188.  
  189. #ifndef _ODUTILS_
  190. #include <ODUtils.h>
  191. #endif
  192.  
  193. #ifndef SOM_ODMenuBar_xh
  194. #include <MenuBar.xh>
  195. #endif
  196.  
  197. #ifndef SOM_Module_OpenDoc_Commands_defined
  198. #include <CmdDefs.xh>
  199. #endif
  200.  
  201. #ifndef _ITEXT_
  202. #include <IText.h>
  203. #endif
  204.  
  205. #ifndef _ISOSTRING_
  206. #include "ISOStr.h"
  207. #endif
  208.  
  209. #ifndef SOM_ODMessageInterface_xh
  210. #include <MssgIntf.xh>
  211. #endif
  212.  
  213. #ifndef _AEOBJECTS_
  214. #include "AEObjects.h"
  215. #endif
  216.  
  217. #ifndef _FOCUSLIB_
  218. #include "FocusLib.h"
  219. #endif
  220.  
  221. #ifndef SOM_ODArbitrator_xh
  222. #include <Arbitrat.xh>
  223. #endif
  224.  
  225. #ifndef SOM_ODWindow_xh
  226. #include <Window.xh>
  227. #endif
  228.  
  229. #ifndef SOM_ODShape_xh
  230. #include <Shape.xh>
  231. #endif
  232.  
  233. #ifndef SOM_ODTransform_xh
  234. #include <Trnsform.xh>
  235. #endif
  236.  
  237. #ifndef _EXCEPT_
  238. #include "Except.h"
  239. #endif
  240.  
  241. #ifndef __MENUS__
  242. #include <Menus.h>
  243. #endif
  244.  
  245. #ifndef __OSUTILS__
  246. #include <OSUtils.h>
  247. #endif
  248.  
  249. #ifndef __TOOLUTILS__
  250. #include <ToolUtils.h>
  251. #endif
  252.  
  253. #ifndef __FONTS__
  254. #include <Fonts.h>
  255. #endif
  256.  
  257. #ifndef __SCRIPT__
  258. #include <Script.h>
  259. #endif
  260.  
  261. #ifndef __TYPES__
  262. #include <Types.h>
  263. #endif
  264.  
  265. #ifndef __PACKAGES__
  266. #include <Packages.h>
  267. #endif
  268.  
  269. #ifndef __RESOURCES__
  270. #include <Resources.h>
  271. #endif
  272.  
  273. #ifndef __DIALOGS__
  274. #include "Dialogs.h"
  275. #endif
  276.  
  277. #ifndef __TEXTEDIT__
  278. #include <TextEdit.h>
  279. #endif
  280.  
  281. #ifndef __PACKAGES__
  282. #include <Packages.h>
  283. #endif
  284.  
  285. #ifndef __STRINGS__
  286. #include <Strings.h>
  287. #endif
  288.  
  289. #ifndef __FP__
  290. #include <Fp.h>
  291. #endif
  292.  
  293. #include <string.h>
  294.  
  295. #ifndef _ODDEBUG_
  296. #include "ODDebug.h"    
  297. #endif
  298.  
  299. #ifndef _STDTYPIO_
  300. #include "StdTypIO.h"
  301. #endif
  302.  
  303. #ifndef _INFOUTIL_
  304. #include <InfoUtil.h>
  305. #endif
  306.  
  307. #ifndef _WINUTILS_
  308. #include "WinUtils.h"
  309. #endif
  310.  
  311. #ifndef _ITEXT_
  312. #include <IText.h>
  313. #endif
  314.  
  315. #ifndef _PASCLSTR_
  316. #include "PasclStr.h"
  317. #endif
  318.  
  319. #ifndef _STORUTIL_
  320. #include <StorUtil.h>
  321. #endif
  322.  
  323. #ifndef _POUTILS_
  324. #include <POUtils.h>    // for UpdateModificationInfo
  325. #endif
  326.  
  327. #ifndef _CLOCKOBJ_
  328. #include "ClockObj.h"
  329. #endif
  330.  
  331. #ifndef SOM_ClockSI_xh
  332. #include "ClockSI.xh"
  333. #endif
  334.  
  335. #ifndef __AEPACKOBJECT__
  336. #include <AEPackObject.h>
  337. #endif
  338.  
  339. #ifndef SOM_Module_OpenDoc_ODRegistry_defined
  340. #include "ODRgstry.xh"
  341. #endif
  342.  
  343. #ifndef __ASREGISTRY__
  344. #include <ASRegistry.h>
  345. #endif
  346.  
  347. #ifndef _TEMPOBJ_
  348. #include <TempObj.h>
  349. #endif
  350.  
  351. #ifndef _SEUTILS_
  352. #include "SEUtils.h"
  353. #endif
  354.  
  355. #ifndef _ODDESUTL_
  356. #include <ODDesUtl.h>
  357. #endif
  358.  
  359. #ifndef SOM_ODAddressDesc_xh
  360. #include "ODAdrDes.xh"
  361. #endif
  362.  
  363. #ifndef SOM_ODAppleEvent_xh
  364. #include <ODAplEvt.xh>
  365. #endif
  366.  
  367. #define ODDebugLayers 0
  368.  
  369. //=========================================================================
  370. // Local Functions
  371. //=========================================================================
  372.  
  373. static ODFrame* AquirePersistantFrame(Environment* ev, ODFrame* frame);
  374.  
  375. //=========================================================================
  376. // ClockPart
  377. //=========================================================================
  378.  
  379. ClockPart::ClockPart()
  380. {
  381.     fContentFrames = kODNULL;                        // Create an empty collection for storing the list 
  382.                                                 // of frames to display    the "clock" in.    
  383.     
  384.     fFont   = GetSysFont();                    // Script Mgr: get the current system font
  385.     fSize   = GetDefFontSize();                // Script Mgr: get the current default font size
  386.     fStyle  = normal;                            // Font Mgr: enum for plain style
  387.  
  388.     fLastAscent = 0;                                // Ascent of the fFont font - used in positioning for drawing
  389.     
  390.     fFontMenu = kODNULL;
  391.     fSizeMenu = kODNULL;
  392.     fStyleMenu = kODNULL;
  393.     fViewMenu = kODNULL;
  394.     fExtraMenu = kODNULL;
  395.     fExtraSubMenu = kODNULL;
  396.     fMenuBar = kODNULL;
  397.     fSemanticInterface = kODNULL;
  398.     fTestClockSU = kODNULL;
  399.     fWorkPort = kODNULL;
  400.     
  401.     fAlarmEnabled = kODFalse;
  402.     fAnalog = kODFalse;
  403.     
  404.     fPartWrapper = kODNULL;
  405.     fSOMSelf = kODNULL;
  406.     
  407.     fModalFocus = kODNULL;
  408.     fFrameView = kODNULL;
  409.     fTimePresentation = kODNULL;
  410.     fSynchronizePresentation = kODNULL;
  411.     
  412.     fDirty = kODFalse;
  413. }
  414.  
  415. ClockPart::~ClockPart()
  416. {
  417.     Environment* ev = somGetGlobalEnvironment();
  418.  
  419.     ODDeleteObject(fContentFrames);// Release the display frames collection.
  420.                                     // Deletion of memory used by the object will be
  421.                                     // reclaimed when the shell deletes the
  422.                                     // instantiation.
  423.     if (fWorkPort)
  424.         DisposeWindow(fWorkPort);
  425.         //ODDisposePtr(fWorkPort);
  426.     
  427.     delete fSemanticInterface;        // Refcount must be zero by now.
  428. }
  429.  
  430. void ClockPart::InitClockPart(Environment* ev, 
  431.                                 ODSession* session,
  432.                                 ODPart* somSelf, 
  433.                                 ODPart* partWrapper)
  434. {
  435.     if (gClockGlobals)
  436.         gClockGlobals->AcquireGlobals(ev);
  437.     else
  438.     {
  439.         gClockGlobals = new ClockGlobals();
  440.         gClockGlobals->InitClockGlobals(ev, session, partWrapper);
  441.         gClockGlobals->AcquireGlobals(ev);
  442.     }
  443.  
  444.     fSOMSelf = somSelf;
  445.     fPartWrapper = partWrapper;
  446.     
  447.     fSession = session; //$$$$$ fSOMSelf->GetStorageUnit(ev)->GetSession(ev);                
  448.     
  449.     fArbitrator = fSession->GetArbitrator(ev);
  450.     fDispatcher = fSession->GetDispatcher(ev);
  451.     fWindowState = fSession->GetWindowState(ev);
  452.     
  453.     fSemanticInterface = new ClockSI;
  454.     SIHelper* semItfcHelper = new SIHelper;
  455.     semItfcHelper->InitSIHelper(fSession, fSemanticInterface);
  456.     fSemanticInterface->InitCPlusSemanticInterface(ev, somSelf, semItfcHelper, fSession);
  457.     InstallStaticCallbacks(semItfcHelper, this);
  458.  
  459.     Rect r;
  460.     SetRect(&r, 0,0,0,0);
  461.  
  462.     fWorkPort = NewCWindow(NULL, &r, "\p", kODFalse, documentProc, NULL, kODFalse, 0);
  463.     //fWorkPort = NewCWindow((Ptr)ODNewPtr(sizeof(WindowRecord)), &r, "\p", kODFalse, documentProc, NULL, kODFalse, 0);
  464.  
  465.     fModalFocus = fSession->Tokenize(ev, kODModalFocus);
  466.     fFrameView = fSession->Tokenize(ev, kODViewAsFrame);
  467.     fTimePresentation   = fSession->Tokenize(ev, kClockFrame);
  468.     fSynchronizePresentation  = fSession->Tokenize(ev, kSynchronizeFrame);
  469.     fAlarmSettingsPresentation   = fSession->Tokenize(ev, kAlarmSettingsFrame);
  470.     fDisplaySettingsPresentation   = fSession->Tokenize(ev, kDisplaySettingsFrame);
  471.     fDialogPresentation   = fSession->Tokenize(ev, kDialogFrame);
  472.     
  473.     fContentFrames = new OrderedCollection;        // Create an empty collection for storing the list 
  474.                                                 // of frames to display    the "clock" in.    
  475.  
  476.     ODSLong        savedRefNum;
  477.     BeginUsingLibraryResources(savedRefNum);
  478.  
  479.     fFontMenu = NewMenu(kClock_FontMenuID,"\pFont");
  480.     fSizeMenu = NewMenu(kClock_SizeMenuID,"\pSize");
  481.     fStyleMenu = GetMenu(kClock_StyleMenuID);
  482.     DetachResource((Handle) fStyleMenu);
  483.     fSettingsMenu = GetMenu(kClock_SettingsMenuID);
  484.     DetachResource((Handle) fSettingsMenu);
  485.     fViewMenu = GetMenu(kClock_ViewMenuID);
  486.     DetachResource((Handle) fViewMenu);
  487. #if ODDebug
  488.     if (!fFontMenu || !fSizeMenu || !fStyleMenu || !fSettingsMenu || !fViewMenu)
  489.         WARN("Error creating menus");
  490. #endif        
  491.     AppendResMenu( fFontMenu, 'FOND' );
  492.  
  493.     AppendMenu(fSizeMenu,"\p9");                // • • Move to resources for localization
  494.     AppendMenu(fSizeMenu,"\p10");
  495.     AppendMenu(fSizeMenu,"\p11");
  496.     AppendMenu(fSizeMenu,"\p12");
  497.     AppendMenu(fSizeMenu,"\p14");
  498.     AppendMenu(fSizeMenu,"\p18");
  499.     AppendMenu(fSizeMenu,"\p24");
  500.     AppendMenu(fSizeMenu,"\p36");
  501.  
  502.     EndUsingLibraryResources(savedRefNum);
  503.     this->BuildMenuBar(ev);
  504.  
  505. }
  506.  
  507. void ClockPart::PrepareStorage(Environment* ev, ODStorageUnit* storageUnit)
  508. {
  509.     storageUnit->AddProperty(ev, kODPropContents)->AddValue(ev, kODKindTestClock);    
  510.  
  511.     fTestClockSU = storageUnit->GetDraft(ev)->CreateStorageUnit(ev);
  512.  
  513.     fTestClockSU->AddProperty(ev,kPropClockType)->AddValue(ev, kODBoolean);    
  514.     fTestClockSU->AddProperty(ev,kPropClockFont)->AddValue(ev, kODUShort);    
  515.     fTestClockSU->AddProperty(ev,kPropClockStyle)->AddValue(ev, kODUShort);            
  516.     fTestClockSU->AddProperty(ev,kPropClockSize)->AddValue(ev, kODUShort);        
  517.     fTestClockSU->AddProperty(ev,kODPropDisplayFrames)->AddValue(ev, kODWeakStorageUnitRefs);
  518.     fDirty = kODTrue;
  519. }
  520.  
  521. void ClockPart::Release(Environment* ev)
  522. {
  523.     // SOM method has already called parent_Release()
  524.     
  525.     if ( fSOMSelf->GetRefCount(ev) == 0 )
  526.         fSOMSelf->GetStorageUnit(ev)->GetDraft(ev)->ReleasePart(ev, fPartWrapper);
  527. }
  528.  
  529. void ClockPart::ReleaseAll(Environment* ev)
  530. {
  531.     ODFinalReleaseObject(ev,fSemanticInterface);
  532.     ODReleaseObject(ev,fMenuBar);
  533.     ODReleaseObject(ev,fTestClockSU);
  534.  
  535.     if (gClockGlobals)
  536.         gClockGlobals->ReleaseGlobals(ev);
  537.  
  538.     OrderedCollectionIterator iter(fContentFrames);
  539.     
  540.     for (ODFrame* aFrame = (ODFrame*)iter.First(); 
  541.                             iter.IsNotComplete();
  542.                             aFrame = (ODFrame*)iter.Next())
  543.     {
  544.         ODReleaseObject(ev, aFrame);
  545.     }
  546. }
  547.  
  548. void ClockPart::Internalize(Environment* ev, ODStorageUnit* storageUnit)
  549. {
  550.     ODULong valueSize, offset;
  551.     ODStorageUnitRef aSURef;
  552.     ODFrame* aFrame;
  553.     ODStorageUnit* su;
  554.     
  555.     su = storageUnit; //$$$$$ somSelf->GetStorageUnit(ev);
  556.     su->Focus(ev, kODPropContents,kODPosSame,kODKindTestClock,1,kODPosFirstSib);
  557.     StorageUnitGetValue(su, ev, sizeof(ODStorageUnitRef),&aSURef);
  558.     if (su->IsValidStorageUnitRef(ev, aSURef))
  559.         fTestClockSU = su->GetDraft(ev)->AcquireStorageUnit(ev, su->GetIDFromStorageUnitRef(ev, aSURef));
  560.     else
  561.         WARN("No Clock SU");
  562.     su = fTestClockSU;
  563.     
  564.     su->Focus(ev, kPropClockType,kODPosSame,kODBoolean,1,kODPosFirstSib);
  565.     StorageUnitGetValue(su, ev, sizeof(ODBoolean), (ODValue)&fAnalog);
  566.     su->Focus(ev, kPropClockFont,kODPosSame,kODUShort,1,kODPosFirstSib);
  567.     StorageUnitGetValue(su, ev, sizeof(ODSShort), (ODValue)&fFont);
  568.     su->Focus(ev, kPropClockStyle,kODPosSame,kODUShort,1,kODPosFirstSib);
  569.     StorageUnitGetValue(su, ev, sizeof(ODSShort), (ODValue)&fStyle);
  570.     su->Focus(ev, kPropClockSize,kODPosSame,kODUShort,1,kODPosFirstSib);
  571.     StorageUnitGetValue(su, ev, sizeof(ODSShort), (ODValue)&fSize);
  572.     
  573.     //$$$$$ CloneInto does not currently externalize display frames
  574.     if ( su->Exists(ev,kODPropDisplayFrames, kODNULL, 0) )
  575.     {
  576.         su->Focus(ev, kODPropDisplayFrames,kODPosUndefined,0,1,kODPosFirstSib);
  577.         valueSize = su->GetSize(ev);
  578.         for (offset = 0; offset < valueSize; offset += sizeof(ODStorageUnitRef))
  579.         {
  580.             su->SetOffset(ev, offset);
  581.             StorageUnitGetValue(su, ev, sizeof(ODStorageUnitRef), (ODValue)&aSURef);
  582.             
  583.             if (su->IsValidStorageUnitRef(ev, aSURef)) {
  584.                 aFrame = su->GetDraft(ev)->AcquireFrame(ev, su->GetIDFromStorageUnitRef(ev, aSURef));
  585.                 this->AddContentFrame(ev, aFrame);
  586.                 aFrame->Release(ev); // Because both AddContentFrame and GetFrame increment
  587.             }
  588.             else 
  589.                 aFrame = kODNULL;
  590.         }
  591.     }
  592.     fDirty = kODFalse;
  593.     // We should minimize the frame shape here, but we can't because I think that
  594.     // the _fClockPart->fPart and _fClockPart->fPartInfo for the frame hasn't been set up yet.
  595.     // somSelf->AdjustFrameShape(ev, dispFrame);    
  596. }
  597.  
  598.  
  599. ODInfoType ClockPart::ReadPartInfo(Environment *ev,
  600.                                 ODFrame* frame, 
  601.                                 ODStorageUnitView*    storageUnitView)
  602. {
  603.     if (storageUnitView->GetSize(ev))
  604.     {
  605.         ClockTimeFrame* partInfo = new ClockTimeFrame();
  606.         partInfo->InitClockTimeFrame(ev, fSession, frame, this);
  607.         
  608.         /*
  609.         ODBoolean needsActivating;
  610.         StorageUnitGetValue(storageUnitView, ev, sizeof(ODBoolean),
  611.                                     (ODValue)&(needsActivating));
  612.         partInfo->fNeedsFoci = needsActivating;
  613.         */                                
  614.         return (ODInfoType)partInfo;
  615.     }
  616.     else
  617.         return ((ODInfoType)kODNULL);
  618. }
  619.  
  620. void ClockPart::Externalize(Environment *ev)
  621. {
  622.     ODFrame* aFrame;
  623.     ODStorageUnitRef aSURef;
  624.     ODULong offset, offsetLimit;
  625.     ODStorageUnit* su = fTestClockSU;
  626.  
  627.     if (fDirty)
  628.     {
  629.         su->Focus(ev, kPropClockType,kODPosSame,kODBoolean,1,kODPosFirstSib);
  630.         StorageUnitSetValue(su, ev, sizeof(ODBoolean), (ODValue)&fAnalog);
  631.         su->Focus(ev, kPropClockFont,kODPosSame,kODUShort,1,kODPosFirstSib);
  632.         StorageUnitSetValue(su, ev, sizeof(ODSShort), (ODValue)&fFont);
  633.         su->Focus(ev, kPropClockStyle,kODPosSame,kODUShort,1,kODPosFirstSib);
  634.         StorageUnitSetValue(su, ev, sizeof(ODSShort), (ODValue)&fStyle);
  635.         su->Focus(ev, kPropClockSize,kODPosSame,kODUShort,1,kODPosFirstSib);
  636.         StorageUnitSetValue(su, ev, sizeof(ODSShort), (ODValue)&fSize);
  637.         
  638.         OrderedCollectionIterator aIter(fContentFrames);
  639.         ODSUForceFocus(ev, su, kODPropDisplayFrames, kODWeakStorageUnitRefs);
  640.         //su->Focus(ev, kODPropDisplayFrames,kODPosUndefined,0,1,kODPosFirstSib);
  641.         offsetLimit = su->GetSize(ev);
  642.         offset = 0;
  643.         for (aFrame = (ODFrame*)aIter.First(); aIter.IsNotComplete();
  644.                                                 aFrame = (ODFrame*)aIter.Next(),
  645.                                                 offset+=sizeof(ODStorageUnitRef))
  646.         {
  647.             su->GetWeakStorageUnitRef(ev, aFrame->GetStorageUnit(ev)->GetID(ev), aSURef);
  648.             su->SetOffset(ev, offset);
  649.             StorageUnitSetValue(su, ev, sizeof(ODStorageUnitRef), aSURef);
  650.         }
  651.         if (offset < offsetLimit)
  652.             su->DeleteValue(ev, offsetLimit - offset);
  653.             
  654.         su = fSOMSelf->GetStorageUnit(ev);
  655.         su->Focus(ev, kODPropContents,kODPosSame,kODKindTestClock,1,kODPosFirstSib);
  656.         su->GetStrongStorageUnitRef(ev, fTestClockSU->GetID(ev), aSURef);
  657.         StorageUnitSetValue(su, ev, sizeof(ODStorageUnitRef),aSURef);
  658.         fDirty = kODFalse;
  659.     }
  660. }
  661.  
  662. void ClockPart::CloneInto(Environment *ev,
  663.                 ODDraftKey key,
  664.                 ODStorageUnit* storageUnit,
  665.                 ODFrame* scopeFrame)
  666. {
  667.     ODStorageUnitRef aSURef;
  668.  
  669.     ODStorageUnit* su = storageUnit->GetDraft(ev)->CreateStorageUnit(ev);
  670.     
  671.     //$$$$$$ ODSUForceFocus is not a public utility
  672.  
  673.     ODSUForceFocus(ev, su, kPropClockType, kODBoolean);
  674.     StorageUnitSetValue(su, ev, sizeof(ODBoolean), (ODValue)&fAnalog);
  675.     ODSUForceFocus(ev, su, kPropClockFont, kODUShort);
  676.     StorageUnitSetValue(su, ev, sizeof(ODSShort), (ODValue)&fFont);
  677.     ODSUForceFocus(ev, su, kPropClockStyle, kODUShort);
  678.     StorageUnitSetValue(su, ev, sizeof(ODSShort), (ODValue)&fStyle);
  679.     ODSUForceFocus(ev, su, kPropClockSize, kODUShort);
  680.     StorageUnitSetValue(su, ev, sizeof(ODSShort), (ODValue)&fSize);
  681.     
  682.     //$$$$$ Display Frames?
  683.     /*OrderedCollectionIterator aIter(fContentFrames);
  684.     su->Focus(ev, kODPropDisplayFrames,kODPosUndefined,0,1,kODPosFirstSib);
  685.     offsetLimit = su->GetSize(ev);
  686.     offset = 0;
  687.     for (aFrame = (ODFrame*)aIter.First(); aIter.IsNotComplete();
  688.                                             aFrame = (ODFrame*)aIter.Next(),
  689.                                             offset+=sizeof(ODStorageUnitRef))
  690.     {
  691.         su->GetWeakStorageUnitRef(ev, aFrame->GetStorageUnit(ev)->GetID(ev), aSURef);
  692.         su->SetOffset(ev, offset);
  693.         StorageUnitSetValue(su, ev, sizeof(ODStorageUnitRef), aSURef);
  694.     }
  695.     if (offset < offsetLimit)
  696.         su->DeleteValue(ev, offsetLimit - offset);
  697.     */    
  698.  
  699.     ODSUForceFocus(ev, storageUnit, kODPropContents, kODKindTestClock);
  700.     storageUnit->GetStrongStorageUnitRef(ev, su->GetID(ev), aSURef);
  701.     StorageUnitSetValue(storageUnit, ev, sizeof(ODStorageUnitRef),aSURef);
  702.     ODReleaseObject(ev, su);
  703. }
  704.  
  705. ODTypeToken ClockPart::CheckPresentation(Environment* ev, ODFrame* frame)
  706. {
  707.     ODTypeToken presentation = frame->GetPresentation(ev);
  708.     if ((presentation != fTimePresentation)
  709.         && (presentation != fSynchronizePresentation)
  710.         && (presentation != fAlarmSettingsPresentation)
  711.         && (presentation != fDisplaySettingsPresentation)
  712.         && (presentation != fDialogPresentation))
  713.     {
  714.         presentation = fTimePresentation;
  715.         frame->SetPresentation(ev, presentation);
  716.     }
  717.     return presentation;
  718. }
  719.  
  720. ClockFrame* ClockPart::CreateClockFrame(Environment* ev, ODFrame* frame, ODTypeToken presentation)
  721. {
  722.     ClockFrame* clockFrame = kODNULL;
  723.     if (presentation == fTimePresentation)
  724.     {
  725.         ClockTimeFrame* timeFrame = new ClockTimeFrame();
  726.         timeFrame->InitClockTimeFrame(ev, fSession, frame, this);
  727.         clockFrame = timeFrame;
  728.     }
  729.     else if (presentation == fSynchronizePresentation)
  730.     {
  731.         ClockSynchroDialogFrame* dialogFrame = new ClockSynchroDialogFrame();
  732.         dialogFrame->InitClockSynchroDialogFrame(ev, fSession, frame, this);
  733.         clockFrame = dialogFrame;
  734.     }
  735.     else if (presentation == fAlarmSettingsPresentation)
  736.     {
  737.         ClockAlarmSettingsDialogFrame* dialogFrame = new ClockAlarmSettingsDialogFrame();
  738.         dialogFrame->InitClockAlarmSettingsDialogFrame(ev, fSession, frame, this);
  739.         clockFrame = dialogFrame;
  740.     }
  741.     else if (presentation == fDisplaySettingsPresentation)
  742.     {
  743.         ClockDisplaySettingsDialogFrame* dialogFrame = new ClockDisplaySettingsDialogFrame();
  744.         dialogFrame->InitClockDisplaySettingsDialogFrame(ev, fSession, frame, this);
  745.         clockFrame = dialogFrame;
  746.         clockFrame->SetShouldDeleteWindow(kODFalse);
  747.     }
  748.     else if (presentation == fDialogPresentation)
  749.     {
  750.         ClockDialogFrame* dialogFrame = new ClockDialogFrame();
  751.         dialogFrame->InitClockDialogFrame(ev, fSession, frame, this);
  752.         clockFrame = dialogFrame;
  753.         clockFrame->SetShouldDeleteWindow(kODFalse);
  754.     }
  755.     return clockFrame;
  756. }
  757.  
  758.  
  759. void ClockPart::DisplayFrameAdded(Environment *ev,
  760.                                   ODFrame* frame)
  761. {
  762.     // We check for an existing ClockFrame in Part Info, because DisplayFrameAdded
  763.     // can get called multiple times, eg. when changing parts. 
  764.     // However DisplayFrameRemoved should probably delete the Part Info
  765.     
  766.     ClockFrame* clockFrame = (ClockFrame*) frame->GetPartInfo(ev);
  767.     if (clockFrame == kODNULL)
  768.     {
  769.         ODTypeToken presentation = this->CheckPresentation(ev, frame);
  770.         clockFrame = this->CreateClockFrame(ev, frame, presentation);
  771.         frame->SetPartInfo(ev, (ODInfoType) clockFrame);            
  772.     }
  773.     if (clockFrame)
  774.     {
  775.         clockFrame->SetPart(ev, this);
  776.         clockFrame->Add(ev);
  777.     }
  778. }
  779.  
  780. void ClockPart::DisplayFrameConnected(Environment *ev,
  781.                                   ODFrame* frame)
  782. {
  783.     ClockFrame* clockFrame = (ClockFrame*) frame->GetPartInfo(ev);
  784.     if (clockFrame == kODNULL)
  785.     {
  786.         ODTypeToken presentation = this->CheckPresentation(ev, frame);
  787.         clockFrame = this->CreateClockFrame(ev, frame, presentation);
  788.         frame->SetPartInfo(ev, (ODInfoType) clockFrame);            
  789.     }
  790.     if (clockFrame)
  791.     {
  792.         clockFrame->SetPart(ev, this);
  793.         clockFrame->Connect(ev);
  794.     }
  795. }
  796.  
  797. void ClockPart::DisplayFrameRemoved(Environment *ev,
  798.                                   ODFrame* frame)
  799. {
  800.     // We don't check _fClockPart->ContainsDisplayFrame because
  801.     // dialog frames are not added to the list
  802.     if ( this->ContainsDisplayFrame(ev, frame))
  803.     {
  804.     
  805.         ClockFrame* clockFrame = (ClockFrame*) frame->GetPartInfo(ev);
  806.         clockFrame->Remove(ev);
  807.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  808.         delete clockFrame;
  809.     }
  810.     else
  811.     {
  812.         ClockFrame* clockFrame = (ClockFrame*) frame->GetPartInfo(ev);
  813.         clockFrame->Remove(ev);
  814.     }
  815.  
  816. }
  817.  
  818. void ClockPart::DisplayFrameClosed(Environment *ev,
  819.                                   ODFrame* frame)
  820. {
  821.     // We don't check _fClockPart->ContainsDisplayFrame because
  822.     // dialog frames are not added to the list
  823.     if ( this->ContainsDisplayFrame(ev, frame))
  824.     {    
  825.         ClockFrame* clockFrame = (ClockFrame*) frame->GetPartInfo(ev);
  826.         
  827.         clockFrame->Close(ev);
  828.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  829.         delete clockFrame;
  830.  
  831.     }
  832.     else
  833.     {
  834.         ClockFrame* clockFrame = (ClockFrame*) frame->GetPartInfo(ev);
  835.         clockFrame->Close(ev);
  836.     }
  837. }
  838.  
  839. ODBoolean ClockPart::ContainsDisplayFrame(Environment* ev, ODFrame* frame)
  840.     if (fContentFrames)
  841.         return fContentFrames->Contains(frame);
  842.     else
  843.         return kODFalse;
  844. }
  845.     
  846. void ClockPart::AddContentFrame(Environment* ev, ODFrame* frame)
  847. {
  848.     if (fContentFrames)
  849.     {
  850.         if (!fContentFrames->Contains(frame))
  851.         {
  852.             fContentFrames->AddLast(frame);
  853.             frame->Acquire(ev);
  854.         }
  855.     }
  856. }
  857.  
  858. void ClockPart::RemoveContentFrame(Environment* ev, ODFrame* frame)
  859. {
  860.     if (fContentFrames && fContentFrames->Contains(frame))
  861.     {
  862.         fContentFrames->Remove(frame);
  863.         ODReleaseObject(ev, frame);
  864.     } else
  865.         WARN("Frame %p is not known to me",frame);
  866. }
  867.  
  868.  
  869. void ClockPart::AdjustDisplayFrames(Environment* ev)
  870. {
  871.     OrderedCollectionIterator iter(fContentFrames);
  872.     
  873.     for (ODFrame* aFrame = (ODFrame*)iter.First(); 
  874.                             iter.IsNotComplete();
  875.                             aFrame = (ODFrame*)iter.Next())
  876.     {
  877.         ClockFrame* clockFrame = (ClockFrame*) aFrame->GetPartInfo(ev);
  878.         clockFrame->Adjust(ev);
  879.     }
  880. }
  881.  
  882. void ClockPart::AdjustDialogs(Environment* ev)
  883. {
  884.     gClockGlobals->AdjustDialogs(ev);
  885. }
  886.  
  887. void ClockPart::BuildMenuBar(Environment* ev)
  888. {
  889.     if ((fMenuBar == kODNULL) || !(fMenuBar->IsValid(ev)))
  890.     {
  891.         fMenuBar = fWindowState->CopyBaseMenuBar(ev);
  892.         fMenuBar->AddMenuLast(ev, kClock_FontMenuID, fFontMenu, fPartWrapper);
  893.         fMenuBar->AddMenuLast(ev, kClock_SizeMenuID, fSizeMenu, fPartWrapper);
  894.         fMenuBar->AddMenuLast(ev, kClock_StyleMenuID,fStyleMenu, fPartWrapper);
  895.         fMenuBar->AddMenuLast(ev, kClock_SettingsMenuID, fSettingsMenu, fPartWrapper);
  896.         fMenuBar->AddMenuLast(ev, kClock_ViewMenuID, fViewMenu, fPartWrapper);
  897.  
  898.         fMenuBar->RegisterCommand(ev, cAnalog, kClock_ViewMenuID, 1);
  899.         fMenuBar->RegisterCommand(ev, cDigital, kClock_ViewMenuID, 2);
  900.         fMenuBar->RegisterCommand(ev, cNewView, kClock_ViewMenuID, 4);
  901.         fMenuBar->RegisterCommand(ev, cSynchronize, kClock_SettingsMenuID, 1);
  902.         fMenuBar->RegisterCommand(ev, cShowDisplaySettings, kClock_SettingsMenuID, 2);
  903.         fMenuBar->RegisterCommand(ev, cShowAlarmSettings, kClock_SettingsMenuID, 3);
  904.         fMenuBar->RegisterCommand(ev, cNewFloater, kClock_SettingsMenuID, 4);
  905.         fMenuBar->RegisterCommand(ev, cNewSinker, kClock_SettingsMenuID, 5);
  906.         fMenuBar->RegisterCommand(ev, cNewMenu, kClock_SettingsMenuID, 6);
  907.     }
  908. }
  909.  
  910. void ClockPart::InstallMenus(Environment* ev)
  911. {
  912.     this->BuildMenuBar(ev);    
  913.     
  914.     fMenuBar->Display(ev);
  915.  
  916.     this->OutlineSizeMenu(ev);
  917.     
  918.     Str255    tFontName;
  919.     
  920.     GetFontName(fFont, tFontName );
  921.     CheckMarkMenu(fFontMenu, tFontName, kODTrue );
  922.  
  923.     Str255    tSizeStr;
  924.     
  925.     NumToString( (ODULong)fSize, tSizeStr );
  926.     CheckMarkMenu(fSizeMenu, tSizeStr, kODTrue);
  927.     
  928.     Str255    tStyleStr;
  929.     
  930.     StyleToString(fStyle, (Str255 *)&tStyleStr);
  931.     CheckMarkMenu(fStyleMenu, tStyleStr, kODTrue );
  932. }
  933.  
  934.  
  935. void ClockPart::OutlineSizeMenu(Environment *ev)
  936. {
  937.     MenuHandle menu = GetMenuHandle( kClock_SizeMenuID );
  938.     
  939.     // (•) Outline the sizes in the font menu that are available
  940.     
  941.     if (RealFont(fFont, 9))
  942.         SetItemStyle( menu, kClock_Size_9Pt, outline );
  943.     else
  944.         SetItemStyle( menu, kClock_Size_9Pt, normal );
  945.  
  946.     if (RealFont(fFont, 10))
  947.         SetItemStyle( menu, kClock_Size_10Pt, outline );
  948.     else
  949.         SetItemStyle( menu, kClock_Size_10Pt, normal );
  950.  
  951.     if (RealFont(fFont, 11))
  952.         SetItemStyle( menu, kClock_Size_11Pt, outline );
  953.     else
  954.         SetItemStyle( menu, kClock_Size_11Pt, normal );
  955.  
  956.     if (RealFont(fFont, 12))
  957.         SetItemStyle( menu, kClock_Size_12Pt, outline );
  958.     else
  959.         SetItemStyle( menu, kClock_Size_12Pt, normal );
  960.  
  961.     if (RealFont(fFont, 14))
  962.         SetItemStyle( menu, kClock_Size_14Pt, outline );
  963.     else
  964.         SetItemStyle( menu, kClock_Size_14Pt, normal );
  965.  
  966.     if (RealFont(fFont, 18))
  967.         SetItemStyle( menu, kClock_Size_18Pt, outline );
  968.     else
  969.         SetItemStyle( menu, kClock_Size_18Pt, normal );
  970.  
  971.     if (RealFont(fFont, 24))
  972.         SetItemStyle( menu, kClock_Size_24Pt, outline );
  973.     else
  974.         SetItemStyle( menu, kClock_Size_24Pt, normal );
  975.  
  976.     if (RealFont(fFont, 36))
  977.         SetItemStyle( menu, kClock_Size_36Pt, outline );
  978.     else
  979.         SetItemStyle( menu, kClock_Size_36Pt, normal );
  980. }
  981.  
  982. void ClockPart::HandleFontMenu(Environment *ev, ODUShort item, ODFrame* frame)
  983. {
  984.     AEDesc        obj, font;
  985.     Str255        fontName;
  986.     ODError        err = noErr;
  987.  
  988.     ODPlatformMenu fontMenu = fMenuBar->GetMenu(ev,kClock_FontMenuID);
  989.     GetMenuItemText( fontMenu, item, fontName );
  990.     THROW_IF_ERROR( AECreateDesc(typeChar, &fontName[1], fontName[0], &font) );
  991.     this->CreatePropObjSpec(ev, pFont, obj);
  992.     TRY
  993.         this->SendSetDataEvent(ev, obj, font, frame);
  994.     CATCH_ALL
  995.         err = ErrorCode();
  996.     ENDTRY
  997.     AEDisposeDesc(&font);
  998.     AEDisposeDesc(&obj);
  999.     THROW_IF_ERROR(err);
  1000. }
  1001.  
  1002. void ClockPart::ShowAboutBox(Environment* ev, ODFrame* frame)
  1003. {
  1004.     TempODFrame currentOwner = fArbitrator->AcquireFocusOwner(ev, fModalFocus);
  1005.     if (fArbitrator->RequestFocus(ev, fModalFocus,frame))
  1006.     {
  1007.         short itemHit;
  1008.         ParamText("\pClock Part…",0,0,0);
  1009.         SetCursor(&ODQDGlobals.arrow);
  1010.         ModalFilterUPP modalFilter = NewModalFilterProc(AboutDialogFilter);
  1011.         
  1012.         ODSLong        savedRefNum;
  1013.         BeginUsingLibraryResources(savedRefNum);
  1014.         DialogPtr aboutDialog = GetNewDialog(kClock_AboutBoxID ,0,(WindowPtr)-1L);
  1015.         EndUsingLibraryResources(savedRefNum);
  1016.  
  1017.         if (aboutDialog)
  1018.         {
  1019.             fWindowState->DeactivateFrontWindows(ev);    // Can be after GetNewDialog because
  1020.                                                         // Dialog is create invisible.
  1021.             ShowWindow(aboutDialog);
  1022.             do
  1023.             {
  1024.                 ModalDialog(modalFilter, &itemHit);
  1025.             } while (itemHit != 1);
  1026.             DisposeDialog(aboutDialog);
  1027.             fWindowState->ActivateFrontWindows(ev);
  1028.         }
  1029.         DisposeRoutineDescriptor(modalFilter);
  1030.  
  1031.         fArbitrator->TransferFocus(ev, fModalFocus,frame, currentOwner);        
  1032.     }
  1033.     else
  1034.         SysBeep(2);
  1035. }
  1036.  
  1037. void ClockPart::ShowSynchDialog(Environment* ev)
  1038. {
  1039.     ODSLong savedRefNum;
  1040.     BeginUsingLibraryResources(savedRefNum);
  1041.     
  1042.     DialogPtr synchDialog = GetNewDialog(kClock_SynchronizeDialogID ,(Ptr)ODNewPtr(sizeof(DialogRecord)),(WindowPtr)-1L);
  1043.         EndUsingLibraryResources(savedRefNum);
  1044.     ODWindow* synchWindow = fWindowState->
  1045.                                     RegisterWindow(ev, synchDialog,
  1046.                                         kODNonPersistentFrameObject,
  1047.                                          kODFalse,    // Keeps draft open
  1048.                                          kODFalse,    // Is resizable
  1049.                                          kODFalse,    // Is floating
  1050.                                          kODFalse, // don't save
  1051.                                          kODFalse,    // should dispose
  1052.                                          fPartWrapper, 
  1053.                                          fFrameView, 
  1054.                                          fSynchronizePresentation, 
  1055.                                          kODNULL);
  1056.     
  1057.     if (synchDialog 
  1058.         && (fArbitrator->RequestFocus(ev, fModalFocus,
  1059.                     synchWindow->GetRootFrame(ev))))
  1060.  
  1061.     {
  1062.         fMenuBar->DisableAll(ev);
  1063.         fMenuBar->EnableCommand(ev,  kODCommandEditMenu, kODTrue ) ;
  1064.         InvalMenuBar();
  1065.         
  1066.         SetCursor(&ODQDGlobals.arrow);
  1067.         synchWindow->Open(ev);
  1068.         synchWindow->Show(ev);
  1069.         synchWindow->Select(ev);
  1070.         ODReleaseObject(ev, synchWindow);
  1071.         
  1072.     }
  1073. }
  1074.  
  1075.  
  1076. void ClockPart::NewFloater(Environment* ev, ODFrame* frame)
  1077. {
  1078.     ODSLong savedRefNum;
  1079.     
  1080.     BeginUsingLibraryResources(savedRefNum);
  1081.     DialogPtr dialog = GetNewDialog(kClock_FloatingDialogID ,0,(WindowPtr)-1L);
  1082.     EndUsingLibraryResources(savedRefNum);
  1083.     
  1084.     ODWindow* window = fSOMSelf->GetStorageUnit(ev)->GetSession(ev)->GetWindowState(ev)->
  1085.                         RegisterWindow(ev, dialog, 
  1086.                             kODNonPersistentFrameObject,
  1087.                              kODFalse,    // Keeps draft open
  1088.                              kODFalse,    // Is resizable
  1089.                              kODTrue, // Is floating
  1090.                              kODFalse,    // don't save
  1091.                              kODTrue,    // should dispose
  1092.                              fPartWrapper,
  1093.                              fFrameView,
  1094.                              fDialogPresentation,
  1095.                              kODNULL);
  1096.  
  1097.     
  1098.     if (dialog && window)
  1099.     {
  1100.         window->Open(ev);
  1101.         window->Show(ev);
  1102.         window->Select(ev);
  1103.     }
  1104.  
  1105.     ODReleaseObject(ev, window);
  1106. }
  1107.  
  1108. void ClockPart::NewSinker(Environment* ev, ODFrame* frame)
  1109. {
  1110.     ODSLong savedRefNum;
  1111.     
  1112.     BeginUsingLibraryResources(savedRefNum);
  1113.     DialogPtr dialog = GetNewDialog(kClock_SinkingDialogID ,0,(WindowPtr)-1L);
  1114.     EndUsingLibraryResources(savedRefNum);
  1115.     
  1116.     ODWindow* window = fSOMSelf->GetStorageUnit(ev)->GetSession(ev)->GetWindowState(ev)->
  1117.                         RegisterWindow(ev, dialog, 
  1118.                                 kODNonPersistentFrameObject,
  1119.                                  kODFalse,    // Keeps draft open
  1120.                                  kODFalse,    // Is resizable
  1121.                                  kODFalse,    // Is floating
  1122.                                  kODFalse,    // don't save
  1123.                                  kODTrue,    // should dispose
  1124.                                  fPartWrapper,
  1125.                                  fFrameView,
  1126.                              fDialogPresentation,
  1127.                                  kODNULL);
  1128.  
  1129.         
  1130.     if (dialog && window)
  1131.     {
  1132.         window->Open(ev);
  1133.         window->Show(ev);
  1134.         window->Select(ev);
  1135.     }
  1136.  
  1137.     ODReleaseObject(ev, window);
  1138. }
  1139.  
  1140. void ClockPart::HandleSizeMenu(Environment *ev, ODUShort item, ODFrame* frame)
  1141. {
  1142.     AEDesc        obj, size;
  1143.     ODError        err = noErr;
  1144.     ODSShort    fontSize = 0;
  1145.  
  1146.     switch (item) 
  1147.     {
  1148.         case kClock_Size_9Pt:    fontSize =  9; break;
  1149.         case kClock_Size_10Pt:    fontSize = 10; break;
  1150.         case kClock_Size_11Pt:    fontSize = 11; break;
  1151.         case kClock_Size_12Pt:    fontSize = 12; break;
  1152.         case kClock_Size_14Pt:    fontSize = 14; break;
  1153.         case kClock_Size_18Pt:    fontSize = 18; break;
  1154.         case kClock_Size_24Pt:    fontSize = 24; break;
  1155.         case kClock_Size_36Pt:    fontSize = 36; break;
  1156.         default:
  1157.             fontSize = 12;
  1158.     }
  1159.     THROW_IF_ERROR( AECreateDesc(typeShortInteger, &fontSize, sizeof(fontSize), &size) );
  1160.     this->CreatePropObjSpec(ev, pPointSize, obj);
  1161.     TRY
  1162.         this->SendSetDataEvent(ev, obj, size, frame);
  1163.     CATCH_ALL
  1164.         err = ErrorCode();
  1165.     ENDTRY
  1166.     AEDisposeDesc(&size);
  1167.     AEDisposeDesc(&obj);
  1168.     THROW_IF_ERROR(err);
  1169. }
  1170.  
  1171. void ClockPart::HandleStyleMenu(Environment *ev, ODUShort item, ODFrame* frame)
  1172. {
  1173.     AEDesc        obj, style;
  1174.     DescType    fontStyle;
  1175.     ODError        err = noErr;
  1176.     
  1177.     switch (item) 
  1178.     {
  1179.         case kClock_Style_Plain:        fontStyle = kAEPlain; break;
  1180.         case kClock_Style_Bold:            fontStyle = kAEBold; break;
  1181.         case kClock_Style_Italic:        fontStyle = kAEItalic; break;
  1182.         case kClock_Style_Underline:    fontStyle = kAEUnderline; break;
  1183.         case kClock_Style_Outline:        fontStyle = kAEOutline; break;
  1184.         case kClock_Style_Shadow:        fontStyle = kAEShadow; break;
  1185.         case kClock_Style_Condense:        fontStyle = kAECondensed; break;
  1186.         case kClock_Style_Extend:        fontStyle = kAEExpanded; break;
  1187.         default:
  1188.             fontStyle = kAEPlain;
  1189.     }
  1190.     
  1191.     THROW_IF_ERROR( AECreateDesc(typeEnumerated, &fontStyle, sizeof(fontStyle), &style) );
  1192.     this->CreatePropObjSpec(ev, pTextStyles, obj);
  1193.     TRY
  1194.         this->SendSetDataEvent(ev, obj, style, frame);
  1195.     CATCH_ALL
  1196.         err = ErrorCode();
  1197.     ENDTRY
  1198.     AEDisposeDesc(&style);
  1199.     AEDisposeDesc(&obj);
  1200.     THROW_IF_ERROR(err);
  1201. }
  1202.  
  1203. void ClockPart::SendClockModeEvent(Environment *ev, ODBoolean analog, ODFrame* frame)
  1204. {
  1205.     AEDesc        obj, mode;
  1206.     DescType    clockMode;
  1207.     ODError        err = noErr;
  1208.     
  1209.     clockMode = kAEDigitalClock;
  1210.     if (analog)
  1211.         clockMode = kAEAnalogClock;
  1212.     THROW_IF_ERROR( AECreateDesc(typeEnumerated, &clockMode, sizeof(clockMode), &mode) );
  1213.     this->CreatePropObjSpec(ev, pDisplayMode, obj);
  1214.     TRY
  1215.         this->SendSetDataEvent(ev, obj, mode, frame);
  1216.     CATCH_ALL
  1217.         err = ErrorCode();
  1218.     ENDTRY
  1219.     AEDisposeDesc(&mode);
  1220.     AEDisposeDesc(&obj);
  1221.     THROW_IF_ERROR(err);
  1222. }
  1223.  
  1224.  
  1225. ODFrame* ClockPart::GetFirstFrame()
  1226. {
  1227.     WASSERT(fContentFrames != kODNULL);
  1228.     ODFrame* frame = (ODFrame*) fContentFrames->First();
  1229.     WASSERT(frame != kODNULL);
  1230.     return frame;
  1231. }
  1232.  
  1233. void ClockPart::SetAnalog(Environment* ev, ODBoolean analog)
  1234. {
  1235.     if (fAnalog != analog) 
  1236.     {
  1237.         fAnalog = analog;
  1238.         fDirty = kODTrue;
  1239.         fSOMSelf->GetStorageUnit(ev)->GetDraft(ev)->SetChangedFromPrev(ev);
  1240.     }
  1241. }
  1242.  
  1243. void ClockPart::SetFont(Environment *ev, ODSShort fontNum)
  1244. {
  1245.     if (fFont != fontNum) 
  1246.     {
  1247.         fFont = fontNum;
  1248.         fDirty = kODTrue;
  1249.         fSOMSelf->GetStorageUnit(ev)->GetDraft(ev)->SetChangedFromPrev(ev);
  1250.     }
  1251. }
  1252.  
  1253. void ClockPart::SetFontSize(Environment *ev, ODSShort fontSize)
  1254. {
  1255.     if (fSize != fontSize) 
  1256.     {
  1257.         fSize = fontSize;
  1258.         fDirty = kODTrue;
  1259.         fSOMSelf->GetStorageUnit(ev)->GetDraft(ev)->SetChangedFromPrev(ev);
  1260.     }
  1261. }
  1262.  
  1263. void ClockPart::SetFontStyle(Environment *ev, ODUByte fontStyle )
  1264. {
  1265.     if (fStyle != fontStyle) 
  1266.     {
  1267.         fStyle = fontStyle;
  1268.         fDirty = kODTrue;
  1269.         fSOMSelf->GetStorageUnit(ev)->GetDraft(ev)->SetChangedFromPrev(ev);
  1270.     }
  1271. }
  1272.  
  1273. ODWindow*  ClockPart::CreateWindow(Environment *ev, WindowProperties& props, ODFrame* rootFrame)
  1274. {
  1275.     ODWindow* window = kODNULL;
  1276.     ODPlatformWindow platformWindow = this->CreatePlatformWindow(props);
  1277.     if (rootFrame)
  1278.     {
  1279.         window =  fSession->GetWindowState(ev)->RegisterWindowForFrame(ev, 
  1280.                                                          platformWindow, 
  1281.                                                          rootFrame,
  1282.                                                          props.isRootWindow,    // Keeps draft open
  1283.                                                          props.isResizable,    // Is resizable
  1284.                                                          props.isFloating,    // Is floating
  1285.                                                          (props.sourceFrame == kODNULL),    // shouldSave
  1286.                                                          kODFalse,    // should dispose
  1287.                                                          props.sourceFrame);
  1288.     }
  1289.     else
  1290.     {    
  1291.         window =  fWindowState->
  1292.                     RegisterWindow(ev, platformWindow, 
  1293.                                 kODFrameObject,
  1294.                                 props.isRootWindow,            // is root
  1295.                                 props.isResizable,                // Is resizable
  1296.                                 props.isFloating,                // Is floating
  1297.                                 (props.sourceFrame == kODNULL),    // should save
  1298.                                 kODFalse,    // should dispose
  1299.                                 fPartWrapper, 
  1300.                                 fFrameView, 
  1301.                                 fTimePresentation, 
  1302.                                 props.sourceFrame);
  1303.     }
  1304.     return window;
  1305. }
  1306.  
  1307. ODBoolean ClockPart::HandleOSEvent(Environment* ev, ODEventData* event, ODFrame* frame, ODFacet* facet)
  1308. {
  1309.     const short     kSuspendResumeMessage = 0x01;    // Resume vs. suspend mask
  1310.     unsigned char     typeOSEvent;
  1311.     
  1312.     // • Is it a multifinder event?
  1313.     typeOSEvent = (unsigned char) (event->message >> 24) & 0x00FF;
  1314.     
  1315.     // • Switch on the type of OSEvent that occurred, high byte of message is event type
  1316.     switch (typeOSEvent) 
  1317.     {                     
  1318.         case kSuspendResumeMessage:
  1319.             {
  1320.                 ClockFrame* clockFrame = (ClockFrame*) frame->GetPartInfo(ev);
  1321.                 const short kResumeMask = 0x01;    // High byte suspend/resume event 
  1322.                 ODBoolean    goingToBackground = (event->message & kResumeMask) == 0;
  1323.                 
  1324.                 if (goingToBackground)
  1325.                 {
  1326. #if defined(ODDebug) && ODDebugLayers
  1327.     somPrintf("Clock Going to Background. Frame: %x Facet: %x\n", frame, facet);
  1328. #endif
  1329.                     clockFrame->SuspendProcess(ev);    
  1330.                 }
  1331.                 else
  1332.                 {
  1333. #if defined(ODDebug) && ODDebugLayers
  1334.     somPrintf("Clock Coming to Foreground. Frame: %x Facet: %x\n", frame, facet);
  1335. #endif
  1336.                     clockFrame->ResumeProcess(ev);    
  1337.                     
  1338.                 }
  1339.             }
  1340.         default:
  1341.             break;
  1342.     }
  1343.     return kODTrue;
  1344. }
  1345.  
  1346. ODID ClockPart::OpenInitialWindow(Environment *ev)
  1347. {
  1348.     ODWindow* window = kODNULL;
  1349.     WindowProperties props;
  1350.     this->GetDefaultWindowProperties(ev, &props, kODNULL);
  1351.  
  1352.     window = this->CreateWindow(ev, props, kODNULL);
  1353.     ODID windowID = window->GetID(ev);
  1354.     window->Open(ev);
  1355.     window->Show(ev);
  1356.     window->Select(ev);    
  1357.     ODReleaseObject(ev, window);    
  1358.     return windowID;            
  1359. }
  1360.  
  1361. void ClockPart::GetDefaultWindowProperties(Environment* ev, WindowProperties* props, ODFrame* sourceFrame)
  1362. {
  1363.     CopyPascalString(props->title, "\pClock");
  1364.     props->procID = zoomDocProc;
  1365.     props->hasCloseBox = kODTrue;
  1366.     props->refCon = 0;
  1367.     props->wasVisible = kODTrue;
  1368.     props->isResizable = kODTrue;
  1369.     props->isFloating = kODFalse;
  1370.     props->isRootWindow = (sourceFrame == kODNULL);
  1371.     props->shouldShowLinks = kODFalse;
  1372.     props->sourceFrame = sourceFrame;
  1373.  
  1374.     this->CalcClockBounds(props->boundsRect);
  1375.     if (!fAnalog)
  1376.     {
  1377.         props->boundsRect.right += 15;
  1378.         props->boundsRect.bottom += 15;
  1379.     }
  1380.     OffsetRect(&props->boundsRect, 40, 40);
  1381.  
  1382.     ODName* windowName = kODNULL;
  1383.     if (sourceFrame)
  1384.         windowName = ODGetPartName(ev, sourceFrame, kODNULL);
  1385.     if (windowName==kODNULL || GetITextStringLength(windowName)==0)
  1386.         CopyPascalString(props->title, "\pClock");
  1387.     else
  1388.         GetITextPString(windowName, props->title);
  1389.     if (windowName)
  1390.         DisposeIText(windowName);
  1391. }
  1392.  
  1393. ODPlatformWindow ClockPart::CreatePlatformWindow(WindowProperties& props)
  1394. {
  1395.     ODPlatformWindow platformWindow = NewCWindow((Ptr)ODNewPtr(sizeof(WindowRecord)), 
  1396.                                                     &(props.boundsRect), 
  1397.                                                     props.title, 
  1398.                                                     kODFalse /*visible */, 
  1399.                                                     props.procID, 
  1400.                                                     (WindowPtr)-1L, 
  1401.                                                     props.hasCloseBox, 
  1402.                                                     props.refCon);
  1403.     return platformWindow;
  1404. }
  1405.  
  1406. ODID ClockPart::OpenRootFrame(Environment *ev, ODFrame* frame)
  1407. {
  1408.     ODWindow* window = kODNULL;
  1409.     ODID windowID = 0;
  1410.     WindowProperties props;
  1411.     
  1412.     ODBoolean hasWindowProperties = BeginGetWindowProperties(ev, frame, &props);
  1413.     if (!hasWindowProperties)
  1414.         this->GetDefaultWindowProperties(ev, &props, kODNULL);
  1415.     ODPlatformWindow platformWindow = this->CreatePlatformWindow(props);
  1416.     ClockFrame* clockFrame = (ClockFrame*) frame->GetPartInfo(ev);
  1417.     // Set the platform window early, so that if RegisterWindow fails, clockFrame
  1418.     // can still get to the platform window to dispose of it.
  1419.     if (clockFrame)
  1420.         clockFrame->SetPlatformWindow(platformWindow); 
  1421.     TRY{
  1422.         window =  fSession->GetWindowState(ev)->RegisterWindowForFrame(ev, platformWindow, 
  1423.                                                         frame,
  1424.                                                          props.isRootWindow,    // Keeps draft open
  1425.                                                          kODTrue,    // Is resizable
  1426.                                                          kODFalse,    // Is floating
  1427.                                                          kODTrue,    // shouldSave
  1428.                                                          kODFalse,    // should dispose
  1429.                                                          props.sourceFrame);
  1430.     }CATCH_ALL{
  1431.         TRY{
  1432.             EndGetWindowProperties(ev, &props); // Release source frame
  1433.         }CATCH_ALL{
  1434.             //ignore errors
  1435.         }ENDTRY
  1436.         RERAISE;
  1437.     }ENDTRY
  1438.     EndGetWindowProperties(ev, &props); // Release source frame
  1439.     window->Open(ev);
  1440.     window->Show(ev);
  1441.     windowID = window->GetID(ev);
  1442.     ODReleaseObject(ev, window);
  1443.     return windowID;
  1444. }
  1445.  
  1446.  
  1447. void  ClockPart::AdjustMenus(Environment *ev)
  1448. {
  1449.     //fMenuBar->EnableCommand(ev, kODCommandViewAsWin, !frame->IsRoot(ev));
  1450.     fMenuBar->EnableAndCheckCommand(ev, cAnalog , kODTrue, fAnalog);
  1451.     fMenuBar->EnableAndCheckCommand(ev, cDigital , kODTrue, !fAnalog);
  1452.  
  1453.     Str255        fontName;
  1454.     ODPlatformMenu fontMenu = fMenuBar->GetMenu(ev,kClock_FontMenuID);
  1455.     GetFontName(fFont, fontName );
  1456.     CheckMarkMenu(fontMenu, fontName, kODTrue );
  1457.  
  1458.     ODIText*    menuItem;
  1459.     // DON'T DO THIS! FOR LOCALISABILITY, READ THE TEXT OUT OF A RESOURCE AND
  1460.     //    USE THE CURRENT SYSTEM SCRIPT AND CURRENT SYSTEM LANGUAGE.
  1461.     menuItem = CreateIText(smRoman, langEnglish, "About Clock…");
  1462.     fMenuBar->SetItemString(ev, kODCommandAbout, menuItem);
  1463.     DisposeIText(menuItem);
  1464.     
  1465. }
  1466.  
  1467. //------------------------------------------------------------------------------
  1468. // ClockPart: HandleMenuEvent
  1469. //------------------------------------------------------------------------------
  1470.  
  1471.  
  1472. ODBoolean ClockPart::HandleMenuEvent(Environment *ev, ODEventData* event, ODFrame* frame)
  1473. {
  1474.     ODBoolean wasHandled = kODTrue;
  1475.  
  1476.     long menuResult = event->message;
  1477.     short menu = HiWord(menuResult);
  1478.     short item = LoWord(menuResult);
  1479.     ODCommandID command = fMenuBar->GetCommand(ev, menu, item);
  1480.  
  1481.     if (fMenuBar->IsCommandSynthetic(ev, command))    // Font, Size, Style
  1482.     {
  1483.         switch ( menu ) 
  1484.         {
  1485.             case kClock_FontMenuID:    
  1486.                 this->HandleFontMenu(ev, item, frame ); 
  1487.                 break;
  1488.             case kClock_SizeMenuID:    
  1489.                 this->HandleSizeMenu(ev,  item, frame ); 
  1490.                 break;
  1491.             case kClock_StyleMenuID:    
  1492.                 this->HandleStyleMenu(ev, item, frame );
  1493.                 break;
  1494.             default:
  1495.                 wasHandled = kODFalse;
  1496.                 break;
  1497.         }
  1498.         
  1499.     }
  1500.     else
  1501.     {
  1502.         switch (command)
  1503.         {
  1504.             case kODCommandAbout:
  1505.                 this->ShowAboutBox(ev, frame);
  1506.                 break;
  1507.             case cAnalog:
  1508.                 this->SendClockModeEvent(ev, kODTrue, frame);
  1509.                 break;
  1510.             case cDigital:
  1511.                 this->SendClockModeEvent(ev, kODFalse, frame);
  1512.                 break;
  1513.             case cSynchronize:
  1514.                 this->ShowSynchDialog(ev);
  1515.                 break;
  1516.             case cShowAlarmSettings:
  1517.                 gClockGlobals->OpenAlarmSettingsDialog(ev, frame);
  1518.                 break;
  1519.             case cShowDisplaySettings:
  1520.                 gClockGlobals->OpenDisplaySettingsDialog(ev, frame);
  1521.                 this->AdjustDialogs(ev);
  1522.                 break;
  1523.             case cNewFloater:
  1524.                 this->NewFloater(ev, frame);
  1525.                 break;
  1526.             case cNewSinker:
  1527.                 this->NewSinker(ev, frame);
  1528.                 break;
  1529.             case cNewMenu:
  1530.                 {
  1531.                     if (fExtraMenu == kODNULL)
  1532.                     {
  1533.                         fExtraMenu = NewMenu(kClock_ExtraMenuID, "\pMenu");
  1534.                         AppendMenu(fExtraMenu, "\pDelete Me");
  1535.                         fMenuBar->AddMenuBefore(ev, kClock_ExtraMenuID, fExtraMenu, fPartWrapper, kClock_FontMenuID);
  1536.                         fMenuBar->RegisterCommand(ev, cDeleteMenu, kClock_ExtraMenuID, 1);
  1537.                     }
  1538.                     else if (fExtraSubMenu == kODNULL)
  1539.                     {
  1540.                         fExtraSubMenu = NewMenu(kClock_ExtraSubMenuID, "\pSubMenu");
  1541.                         AppendMenu(fExtraSubMenu, "\pSubItem");
  1542.                         AppendMenu(fExtraMenu, "\pHier");
  1543.                         fMenuBar->AddSubMenu(ev, kClock_ExtraSubMenuID, fExtraSubMenu, fPartWrapper);
  1544.                         SetItemCmd(fExtraMenu,2, hMenuCmd);
  1545.                         SetItemMark(fExtraMenu,2, kClock_ExtraSubMenuID);
  1546.                     }
  1547.                     else
  1548.                         SysBeep(2);
  1549.  
  1550.                 }
  1551.                 break;
  1552.             case cDeleteMenu:
  1553.                 {
  1554.                     fMenuBar->UnregisterCommand(ev, cDeleteMenu);
  1555.                     fMenuBar->RemoveMenu(ev, kClock_ExtraMenuID);
  1556.                     fMenuBar->RemoveMenu(ev, kClock_ExtraSubMenuID);
  1557.                     if (fExtraMenu)
  1558.                     {
  1559.                         DisposeMenu(fExtraMenu);
  1560.                         fExtraMenu = kODNULL;
  1561.                     }
  1562.                     if (fExtraSubMenu)
  1563.                     {
  1564.                         DisposeMenu(fExtraSubMenu);
  1565.                         fExtraSubMenu = kODNULL;
  1566.                     }
  1567.                     
  1568.                 }
  1569.                 break;
  1570.             default:
  1571.                 wasHandled = kODFalse;
  1572.                 break;
  1573.         }
  1574.     }
  1575.     return wasHandled;
  1576. }
  1577.  
  1578. ODBoolean ClockPart::CloseWindow(Environment* ev, ODFrame* frame)
  1579. {
  1580.     ODBoolean         handled            = kODFalse;
  1581.     ODTypeToken presentation = frame->GetPresentation(ev);
  1582.     
  1583.     if (presentation == fDisplaySettingsPresentation)
  1584.     {
  1585.         gClockGlobals->CloseDisplaySettingsWindow(ev);
  1586.         handled = kODTrue;
  1587.     }
  1588.     else if (presentation == fAlarmSettingsPresentation)
  1589.     {
  1590.         gClockGlobals->CloseAlarmSettingsWindow(ev);
  1591.         handled = kODTrue;
  1592.     }
  1593.         
  1594.     return handled;
  1595. }
  1596.  
  1597.  
  1598. ODShape* ClockPart::CreateOvalShape(Environment* ev, ODFrame* frame, Rect& rect)
  1599. {
  1600.     GrafPtr savedPort;
  1601.     GetPort(&savedPort);
  1602.     SetPort(fWorkPort);
  1603.     RgnHandle region = ODNewRgn();
  1604.     OpenRgn();
  1605.     FrameOval(&rect);
  1606.     CloseRgn(region);
  1607.     
  1608.     ODShape* newShape = frame->CreateShape(ev);
  1609.     newShape->SetQDRegion(ev, region);
  1610.     SetPort(savedPort);
  1611.     return newShape;
  1612. }
  1613.  
  1614.  
  1615. ClockSI*    ClockPart::AquireSI(Environment* ev)
  1616. {
  1617.     fSemanticInterface->Acquire(ev);
  1618.     return fSemanticInterface;
  1619. }
  1620.  
  1621.  
  1622. #ifndef ff
  1623. #define ff(N)        ( (ODCoordinate)(N) <<16 )    // Converts integer to fixed (ODCoordinate)
  1624. #endif
  1625.  
  1626. void ClockPart::CalcClockBounds(Rect& rect)
  1627. {
  1628.     if (fAnalog)
  1629.         SetRect(&rect, 0,0,150,150);
  1630.     else
  1631.     {
  1632.         GrafPtr savedPort;
  1633.         GetPort(&savedPort);
  1634.         SetPort(fWorkPort);
  1635.         
  1636.         TextFont(fFont);
  1637.         TextFace(fStyle );
  1638.         TextMode(srcCopy );
  1639.         TextSize(fSize );
  1640.     
  1641.         FontInfo fontIRec;
  1642.         GetFontInfo( &fontIRec );
  1643.         fLastAscent = fontIRec.ascent;
  1644.         
  1645.                                         // • • move to resource for localization
  1646.         //rect.Set(0, 0, ff(StringWidth("\p12:59:59 MM")+4),
  1647.         //              ff((fontIRec.ascent+fontIRec.descent+fontIRec.leading)+2) );
  1648.         SetRect(&rect, 0, 0, StringWidth("\p12:59:59 MM")+4,
  1649.                       (fontIRec.ascent+fontIRec.descent+fontIRec.leading)+2 );
  1650.         SetPort(savedPort);
  1651.     }
  1652. }    // ClockPart::CalcClockBounds
  1653.  
  1654.  
  1655. void ClockPart::CreatePropObjSpec(Environment* ev, DescType prop, AEDesc& objSpec)
  1656. {
  1657.     AEDesc                    nullDesc = NULL_DESCRIPTOR_DEFINITION;
  1658.     AEDesc                    pr = NULL_DESCRIPTOR_DEFINITION;
  1659.     DescType                activePart;
  1660.  
  1661.     // create "prop of active part" reference
  1662.     activePart = pActivePart;
  1663.     TRY
  1664.         // active part
  1665.         THROW_IF_ERROR( AECreateDesc(typeType, (Ptr) &activePart, sizeof(activePart), &pr) );
  1666.         THROW_IF_ERROR( CreateObjSpecifier(cProperty, &nullDesc, formPropertyID, &pr, kODTrue, &objSpec) );
  1667.         // prop of active part
  1668.         THROW_IF_ERROR( AECreateDesc(typeType, (Ptr) &prop, sizeof(prop), &pr) );
  1669.         THROW_IF_ERROR( CreateObjSpecifier(cProperty, &objSpec, formPropertyID, &pr, kODTrue, &objSpec) );
  1670.     CATCH_ALL
  1671.         AEDisposeDesc(&pr);
  1672.         RERAISE;
  1673.     ENDTRY
  1674. }    // ClockPart::CreatePropObjSpec
  1675.  
  1676.  
  1677. void ClockPart::SendSetDataEvent(Environment* ev, AEDesc& objSpec, AEDesc& data, ODFrame* frame)
  1678. {
  1679.     ODAddressDesc*        address = kODNULL;
  1680.     ODAppleEvent*        event = kODNULL;
  1681.     ODAppleEvent*        reply = kODNULL;
  1682.     AEDesc                aeevent = NULL_DESCRIPTOR_DEFINITION;
  1683.     ODMessageInterface*    mess = kODNULL;
  1684.     ODError                err = noErr;
  1685.     TempODFrame            activeFrame = AquirePersistantFrame(ev, frame);
  1686.     TempODPart            part = activeFrame->AcquirePart(ev);
  1687.     AEDesc                nullDesc = NULL_DESCRIPTOR_DEFINITION;
  1688.     AEDesc                subject = NULL_DESCRIPTOR_DEFINITION;
  1689.     AEDesc                pr = NULL_DESCRIPTOR_DEFINITION;
  1690.     DescType            activePart;
  1691.  
  1692.     ODVolatile(address);
  1693.     ODVolatile(event);
  1694.     ODVolatile(reply);
  1695.  
  1696.     TRY
  1697.         // get the message interface
  1698.         mess = fSOMSelf->GetStorageUnit(ev)->GetSession(ev)->GetMessageInterface(ev);
  1699.         // create an event
  1700.         mess->CreatePartAddrDesc(ev, &address, fSOMSelf);
  1701.         mess->CreateEvent(ev, kAECoreSuite, kAESetData, address, kAnyTransactionID, &event);
  1702.         ODDescToAEDesc(event, &aeevent);
  1703.         // add direct parameter and data parameter
  1704.         THROW_IF_ERROR( AEPutParamDesc(&aeevent, keyDirectObject, &objSpec) );
  1705.         THROW_IF_ERROR( AEPutParamDesc(&aeevent, keyAEData, &data) );
  1706.         // add the active part subject attribute
  1707.         activePart = pActivePart;
  1708.         THROW_IF_ERROR( AECreateDesc(typeType, (Ptr) &activePart, sizeof(activePart), &pr) );
  1709.         THROW_IF_ERROR( CreateObjSpecifier(cProperty, &nullDesc, formPropertyID, &pr, kODTrue, &subject) );
  1710.         THROW_IF_ERROR( AEPutAttributeDesc(&aeevent, keySubjectAttr, &subject) );
  1711.         AEDescToODDesc(&aeevent, event);
  1712.         // create the reply
  1713.         reply = new ODAppleEvent;
  1714.         THROW_IF_NULL(reply);
  1715.         reply->InitODAppleEvent(ev);
  1716.         // send the event with a null frame so no part id subject is added (which would stomp ours)
  1717.         mess->Send(ev, kODNULL, part, event, reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout);
  1718.     CATCH_ALL
  1719.         err = ErrorCode();
  1720.     ENDTRY
  1721.     AEDisposeDesc(&aeevent);
  1722.     AEDisposeDesc(&subject);
  1723. //    AEDisposeDesc(&pr);        // this one should already be disposed by CreateObjectSpecifier
  1724.     ODDeleteObject(address);
  1725.     ODDeleteObject(event);
  1726.     ODDeleteObject(reply);
  1727.     THROW_IF_ERROR(err);
  1728. }
  1729.  
  1730. ODFrame* AquirePersistantFrame(Environment* ev, ODFrame* frame)
  1731. {
  1732.     // Temporary hack to use activeFrame, otherwise we fail when a dialog is up,
  1733.     // because its frame is nonpersistent
  1734.     // A better approach might be to add delegation of menu commands from
  1735.     // dialog frames to the source frame of the dialog window.
  1736.     //TempODFrame activeFrame = fArbitrator->AcquireFocusOwner(ev, fSession->Tokenize(ev, kODSelectionFocus));
  1737.     
  1738.     ODFrame* activeFrame = kODNULL;
  1739.     if (frame->GetStorageUnit(ev) == kODNULL)
  1740.     {
  1741.         TempODWindow window = frame->AcquireWindow(ev);
  1742.         activeFrame = window->AcquireSourceFrame(ev);
  1743.     }
  1744.     else
  1745.     {
  1746.         activeFrame = frame;
  1747.         activeFrame->Acquire(ev);
  1748.     }
  1749.     return activeFrame;
  1750. }
  1751.  
  1752.